package Infix2RPM.processor.Stack;

/*
 *  Infix-RPN conversion using Shunting-Yard algorithm
 */
import java.util.HashMap;
import java.util.Map;

public class OperatorLookup {

	// Associativity constants for operators
	public static final int LEFT_ASSOC = 0;
	public static final int RIGHT_ASSOC = 1;

	// Supported operators
	private static final Map<String, int[]> OPERATORS = new HashMap<String, int[]>();

	static {
		// Map<"token", []{precedence, associativity}>
		OPERATORS.put("+", new int[] { 0, LEFT_ASSOC });
		OPERATORS.put("-", new int[] { 0, LEFT_ASSOC });
		OPERATORS.put("*", new int[] { 5, LEFT_ASSOC });
		OPERATORS.put("/", new int[] { 5, LEFT_ASSOC });
		OPERATORS.put("%", new int[] { 5, LEFT_ASSOC }); // mod
		OPERATORS.put("^", new int[] { 10, RIGHT_ASSOC });  // power

		OPERATORS.put("<", new int[] { 11, LEFT_ASSOC });
		OPERATORS.put("<=", new int[] { 11, LEFT_ASSOC });
		OPERATORS.put(">", new int[] { 11, LEFT_ASSOC });
		OPERATORS.put(">=", new int[] { 11, LEFT_ASSOC });
		
		OPERATORS.put("||", new int[] { 12, LEFT_ASSOC });
		OPERATORS.put("&&", new int[] { 12, LEFT_ASSOC });
	}

	/**
	 * Test if token is an operator .
	 * 
	 * @param token
	 *            The token to be tested .
	 * @return True if token is an operator . Otherwise False .
	 */
	public static boolean isOperator(final String token) {
		return OPERATORS.containsKey(token);
	}

	/**
	 * Test the associativity of an operator token .
	 * 
	 * @param token
	 *            The token to be tested (needs to be an operator).
	 * @param type
	 *            LEFT_ASSOC or RIGHT_ASSOC
	 * @return True if the tokenType equals the input parameter type .
	 */
	public static boolean isAssociative(final String token, final int type) {
		if (!isOperator(token)) {
			throw new IllegalArgumentException("Invalid token: " + token);
		}
		if (OPERATORS.get(token)[1] == type) {
			return true;
		}
		return false;
	}

	/**
	 * Compare precedence of two operators.
	 * 
	 * @param token1
	 *            The first operator .
	 * @param token2
	 *            The second operator .
	 * @return A negative integer if token1 has a smaller precedence than token2,
	 *         0 if the precedence of each of the two tokens are equal, a positive
	 *         integer is returned.
	 */
	public static final int cmpPrecedence(final String token1,
			final String token2) {
		if (!isOperator(token1) || !isOperator(token2)) {
			throw new IllegalArgumentException("Invalied tokens: " + token1
					+ " " + token2);
		}
		return OPERATORS.get(token1)[0] - OPERATORS.get(token2)[0];
	}
}